$.fn.autoCompleter = function (options) {
    // 默认选项
    var opt = {
        single: false, // 是否单选
        max: 5,
        url: '',

        mail: false,
        mailList: ['@qq.com', '@gmail.com', '@126.com', '@163.com', '@sina.com'],

        name: '',
        id: '',
        placeholder: '',

        inputClass: '',
        inputCss: {},

        listClass: '',
        listCss: {},

        listItemClass: '',
        listItemCss: {},

        listItemReadyClass: '',
        listItemReadyCss: {},

        listItemHintClass: '',
        listItemHintCss: {},

        labelClass: '',
        labelCss: {},

        labelItemClass: '',
        labelItemCss: {},

        labelContainerId: '',

        validate: true,
        validateFunc: undefined,
        validateFailStr: '格式错误',
        validateFailFun: function (str) { alert(str + '格式错误'); },
        validateFailRepeat: function (str) { alert(str + '已选择'); },

        cancelSpace: true,
        cancelEnter: false,
        cancelEsc: false,
        cancelArrow: false,

        clickLabelFunc: undefined
    };

    $.extend(true, opt, options);

    var completer = new AutoCompleter(this); // 初始化对象

    var selectedIndex = -1; // 上次输入时选中的提示索引
    var selectList = []; // 可选索引
    var selectItems = [];

    //var selectedElements = (opt.single) ? '' : []; // 已选邮件列表
    var selectedElements;
    if (completer.preset) {
        selectedElements = (opt.single) ? completer.preset : eval(completer.preset);
        renderLabel();
    } else {
        selectedElements = (opt.single) ? '' : [];
    }

    // 点击container使Input获得焦点
    completer.container.on('click', function () {
        completer.input.focus();
    });

    // 输入框获得焦点
    completer.input.on('focus input', function () {
        showBox();
    });

    // 点击区域非输入框或下拉框
    completer.input.on('click', function () {
        return false;
    });

    completer.list.on('click', function () {
        return false;
    });

    $(document).on('click', function () {
        hideBox();
    });

    // 自动提示
    completer.input.on('keyup', function (e) {
        if (!opt.single && selectedElements.length >= opt.max) {
            $(this).blur();
            var alert = '最多允许' + opt.max + "个标签";
            if (muses) {
                muses.open({content: alert});
            } else {
                alert(alert);
            }
            return false;
        }

        if (!opt.cancelSpace && e.keyCode == 32) { // 空格
            var temp = completer.list.find('li.selElementOne.ready');
            if (temp.length == 1) {
                addElementLabel(temp.attr('data-element'));
            }
            // else {
            //     addElementLabel($(this).val().trim());
            // }
        } else if (!opt.cancelEnter && e.keyCode == 13) { // 回车
            var temp = completer.list.find('li.selElementOne.ready');
            if (temp.length == 1) {
                addElementLabel(temp.attr('data-element'));
            }
            // else {
            //     addElementLabel($(this).val().trim());
            // }
        } else if (!opt.cancelEsc && e.keyCode == 27) { // ESC
            hideBox();
        } else {
            if (!opt.mail && (e.keyCode == 38 || e.keyCode == 40)) { // Up and Down
                return;
            }
            renderList($(this).val()); // 渲染选择表
        }
    });

    // 下拉待选项 - 上下键
    completer.input.on('keydown', function (e) {
        if (selectList.length == 0 || opt.cancelArrow) {
            return;
        }
        if (e.keyCode == 40) { // 上键
            if (opt.mail) {
                selectedIndex++;
                while (selectList.indexOf(selectedIndex) == -1 && selectedIndex < opt.mailList.length) {
                    selectedIndex++;
                }
                selectedIndex = (selectedIndex >= opt.mailList.length) ? selectList[0] : selectedIndex;
                e.preventDefault();
                renderList($(this).val());
            } else {
                selectedIndex++;
                while (selectList.indexOf(selectedIndex) == -1 && selectedIndex < selectList.length) {
                    selectedIndex++;
                }
                selectedIndex = (selectedIndex >= selectList.length) ? selectList[0] : selectedIndex;
                e.preventDefault();
                renderStaticAjaxList($(this).val());
            }
        } else if (e.keyCode == 38) { // 下键
            if (opt.mail) {
                selectedIndex--;
                while (selectList.indexOf(selectedIndex) == -1 && selectedIndex >= 0) {
                    selectedIndex--;
                }
                selectedIndex = (selectedIndex < 0) ? selectList[selectList.length - 1] : selectedIndex;
                e.preventDefault();
                renderList($(this).val());
            } else {
                selectedIndex--;
                while (selectList.indexOf(selectedIndex) == -1 && selectedIndex >= 0) {
                    selectedIndex--;
                }
                selectedIndex = (selectedIndex < 0) ? selectList[selectList.length - 1] : selectedIndex;
                e.preventDefault();
                renderStaticAjaxList($(this).val());
            }
        }
    });

    // 下拉待选项 - 鼠标覆盖
    completer.list.on('mouseover', 'li.selElementOne', function () {
        completer.list.find('li.selElementOne')
            .removeClass('ready')
            .removeClass(opt.listItemReadyClass)
            .removeAttr('style');
        $(this).addClass('ready ' + opt.listItemReadyClass)
            .css(opt.listItemReadyCss);
        // 寻找序号
        var temp = $(this).attr('data-element');
        if (temp != undefined) {
            selectedIndex = opt.mailList.indexOf('@' + temp.split('@')[1]);
        }
    });

    // 点击列表项
    completer.list.on('click', 'li.selElementOne.ready', function () {
        addElementLabel($(this).attr('data-element'));
    });

    // 点击标签
    completer.labels.on('click', 'span.selectedItem', function () {
        if ((typeof opt.clickLabelFunc).toLowerCase() == 'function') {
            opt.clickLabelFunc($(this).html());
        } else {
            delElementLabel($(this).html());
        }
    });

    // 添加新标签
    function addElementLabel(str, inx) {
        hideBox();
        if (!confirmMail(str)) {
            opt.confirmFailFun(str);
            if (opt.single) {
                completer.input.val('');
            }
            return false;
        }
        if (selectedElements.indexOf(str) != -1 && !opt.single) {
            opt.confirmFailRep(str);
            return false;
        }
        if (opt.single) { // 单选时
            selectedElements = str;
        } else {
            if (inx >= 0 && inx < selectedElements.length) {
                selectedElements.splice(inx, 0, str);
            } else {
                selectedElements.push(str);
            }
        }
        renderLabel();
    }

    // 删除标签
    function delElementLabel(str, inx) {
        if (opt.single) {
            selectedElements = '';
        } else {
            if (inx == undefined) {
                inx = selectedElements.indexOf(str);
            }
            if (inx >= 0 && inx < selectedElements.length) {
                selectedElements.splice(inx, 1);
            }
        }
        renderLabel();
    }

    // 渲染已选标签
    function renderLabel() {
        if (opt.single) {
            completer.input.val(selectedElements);
        } else {
            completer.labels.html('');
            for (var i = 0, len = selectedElements.length; i < len; i++) {
                var temp = $('<span>').addClass('selectedItem')
                    .addClass(opt.labelItemClass)
                    .attr({'title': '点击删除'})
                    .css(opt.labelItemCss)
                    .html(selectedElements[i]);
                completer.labels.append(temp).append('\n');
            }
        }
    }

    // 验证邮箱格式
    function confirmMail(str) {
        if (!opt.confirm) {
            return true;
        } else if ((typeof opt.confirmFunc).toLowerCase() == 'function') {
            return opt.confirmFunc(str);
        } else {
            var re = /^(\w-*\.*)+@(\w-?)+(\.\w{2,})+$/;
            if (re.test(str)) {
                return true;
            } else {
                return false;
            }
        }
    }

    // 渲染选择表
    function renderList(text) {
        if (opt.mail) {
            renderMailList(text);
        } else {
            renderAjaxList(text);
        }
    };

    function renderMailList(text) {
        completer.list.html('');

        if (text.length == 0) {
            return;
        }

        selectList = [];
        selectItems = [];

        // 提取前半部分，生成所有自动补全，再匹配输入渲染
        var key = text.split('@')[0];
        for (var i = 0, len = opt.mailList.length; i < len; i++) {
            var temp = key + opt.mailList[i];
            if (temp.indexOf(text) == 0) {
                selectList.push(i);
                var tempLi = $('<li>').attr('data-element', temp)
                    .addClass('selElementOne')
                    .addClass(opt.listItemClass)
                    .css(opt.listItemCss);
                //console.log('selectedIndex:' + selectedIndex + ", i:" + i + ", temp:" + temp);
                if (selectedIndex == i) {
                    tempLi.addClass('ready ' + opt.listItemReadyClass)
                        .css(opt.listItemReadyCss);
                }
                var tempSp = $('<span>').addClass('selElementHint')
                    .addClass(opt.listItemHintClass)
                    .css(opt.listItemHintCss);
                tempLi.append(tempSp.html(text)).append(temp.substr(text.length));
                completer.list.append(tempLi);
            }
        }
        // 邮箱验证提醒
        if (selectList.length == 0) {
            var tempLi = $('<li>').addClass('selElementOne')
                .addClass(opt.listItemClass)
                .css(opt.listItemCss);
            tempLi.addClass('ready ' + opt.listItemReadyClass)
                .css(opt.listItemReadyCss);
            var tempSp = $('<span>').addClass('selElementHint')
                .addClass(opt.listItemHintClass)
                .css(opt.listItemHintCss);
            if (!confirmMail(text)) {
                tempLi.append(tempSp.html(opt.confirmFailStr));
            } else {
                tempLi.attr('data-element', text);
                tempLi.append(tempSp.html(text));
            }
            completer.list.append(tempLi);
        }
    };

    function renderAjaxList(text) {
        if (text.length == 0) {
            completer.list.html('');
            return;
        }

        $.ajax({
            url: opt.url + '/' + text,// + '.html',
            type: 'GET',
            async: false,
            dataType: 'json',
            crossDomain: true,
            success: function (data) {
                completer.list.html('');

                selectList = [];
                selectItems = [];

                $.each(data, function (index, item) {
                    selectList.push(index);
                    selectItems.push(item);
                    var tempLi = $('<li>').attr('data-element', item)
                        .addClass('selElementOne')
                        .addClass(opt.listItemClass)
                        .css(opt.listItemCss);
                    //console.log('selectedIndex:' + selectedIndex + ", index:" + index + ", item:" + item);
                    if (selectedIndex == index) {
                        tempLi.addClass('ready ' + opt.listItemReadyClass)
                            .css(opt.listItemReadyCss);
                    }
                    var tempSp = $('<span>').addClass('selElementHint')
                        .addClass(opt.listItemHintClass)
                        .css(opt.listItemHintCss);
                    tempLi.append(tempSp.html(text)).append(item.substr(text.length));
                    completer.list.append(tempLi);
                });
            },
            error: function (data) {
                console.log('error:');
                console.log(data);
            }
        });
    };

    // 渲染选择表
    function renderStaticAjaxList(text) {
        completer.list.html('');

        if (text.length == 0) {
            return;
        }

        $.each(selectList, function (index, item) {
            var position = selectList[index];
            var data = selectItems[position];
            var tempLi = $('<li>').attr('data-element', data)
                .addClass('selElementOne')
                .addClass(opt.listItemClass)
                .css(opt.listItemCss);
            //console.log('selectedIndex:' + selectedIndex + ", index:" + index + ", data:" + data);
            if (selectedIndex == index) {
                tempLi.addClass('ready ' + opt.listItemReadyClass)
                    .css(opt.listItemReadyCss);
            }
            var tempSp = $('<span>').addClass('selElementHint')
                .addClass(opt.listItemHintClass)
                .css(opt.listItemHintCss);
            tempLi.append(tempSp.html(text)).append(data.substr(text.length));
            completer.list.append(tempLi);
        });
    };

    // 下拉框弹出
    function showBox() {
        completer.list.css({
            'display': 'block',
            'left': completer.input.position().left + 'px'
        });
    };

    // 下拉框隐藏
    function hideBox() {
        completer.list.css('display', 'none').html('');
        if (!opt.single) {
            completer.input.val('');
        }
        selectedIndex = -1;
    };

    // 初始化控件对象
    function AutoCompleter(element) {
        this.preset = element.text();

        this.container = element.addClass('MuseAutocompleterContainer field');

        // 已选标签
        if (opt.labelContainerId != '' && $('#' + opt.labelContainerId).length == 1) {
            this.labels = $('#' + opt.labelContainerId);
        } else {
            this.labels = $('<span>').addClass('selectedElementsLabel ' + opt.labelClass)
                .css(opt.labelCss);
        }

        // 输入框
        this.input = $('<input>').attr({
            type: 'text',
            placeholder: opt.placeholder,
            autocomplete: 'off',
            name: opt.name,
            id: opt.id
        })
            .addClass('selectElementInput ' + opt.inputClass)
            .css(opt.inputCss);

        // 下拉选择表
        this.list = $('<ul>').addClass('selectElementsBox ' + opt.listClass)
            .css(opt.listCss);

        // 初始化DOM结构
        this.container.html('');
        if (opt.labelContainerId == '' || $('#' + opt.labelContainerId).length != 1) {
            this.container.append(this.labels);
        }
        this.container.append(this.input).append(this.list);
    }

    AutoCompleter.prototype.getSelecteds = function () { // 获得已选所有标签
        return selectedElements;
    };

    AutoCompleter.prototype.setElement = function (str) {
        if (opt.single) {
            addElementLabel(str);
        }
    };

    AutoCompleter.prototype.clearElement = function () {
        if (opt.single) {
            delElementLabel();
        }
    };

    AutoCompleter.prototype.addSelected = function (str, inx) {
        addElementLabel(str.toString(), parseInt(inx));
    };

    AutoCompleter.prototype.delSelected = function (str, isNum) {
        if (opt.single) {
            delElementLabel();
        } else {
            if (isNum) {
                delElementLabel('', parseInt(str));
            } else {
                delElementLabel(str.toString());
            }
        }
    };

    AutoCompleter.prototype.spliceElement = function (inx, num) {
        if (opt.single) {
            return;
        }
        for (var i = 0; i < num; i++) {
            delElementLabel('', parseInt(inx));
        }
        if (arguments.length > 2) {
            for (var i = arguments.length - 1; i >= 2; i--) {
                addElementLabel(arguments[i].toString(), parseInt(inx));
            }
        }
    };

    AutoCompleter.prototype.editElement = function (str1, str2, isNum) {
        if (opt.single) {
            return;
        }
        if (!isNum) {
            str1 = selectedElements.indexOf(str1);
        }
        str1 = parseInt(str1);
        if (str1 >= 0 && str1 < selectedElements.length) {
            if (!confirmMail(str2)) {
                opt.confirmFailFun(str2);
            } else if (selectedElements.indexOf(str2) != -1) {
                opt.confirmFailRep(str2);
            } else {
                this.spliceElement(str1, 1, str2);
            }
        }
    };

    return completer;
};